module tb();
reg [3:0] in_x;
reg [3:0] in_y;
reg [2:0] sel;
wire [3:0] out_s;
integer i;
integer j;
integer k;
reg of;
reg z;
reg c;
alu alu1(
  .in_x(in_x),
  .in_y(in_y),
  .sel(sel),
  .out_s(out_s)
);
task check;  //测试任务
  input [3:0] results;  //ALU的结果预期正确输出
  input resultof, resultc, resultz;  //ALU的预期溢出，进位，零位
  begin
    if(out_s!=results)  //比较预期结果和测试单元输出的outputs
      begin               //出错时显示
        $display("Error:x=%h,y=%h,ctrl=%b,s should be %h,get %h", in_x, in_y, sel, results, out_s);
      end
    //自行添加溢出，进位和零位的比较
    if(alu1.overflow!=resultof)  //比较预期结果和测试单元输出的outputs
      begin               //出错时显示
        $display("Error:x=%h,y=%h,ctrl=%b,overflow should be %h, get %h", in_x, in_y, sel, resultof, alu1.overflow);
      end
    if(alu1.carry!=resultc)  //比较预期结果和测试单元输出的outputs
      begin               //出错时显示
        $display("Error:x=%h,y=%h,ctrl=%b,carry should be %h, get %h", in_x, in_y, sel, resultc, alu1.carry);
      end
    if(alu1.zero!=resultz)  //比较预期结果和测试单元输出的outputs
      begin               //出错时显示
        $display("Error:x=%h,y=%h,ctrl=%b,zero should be %h, get %h", in_x, in_y, sel, resultz, alu1.zero);
      end
  end
endtask
initial begin
// 测试加法
/*for(i=-8;i<=7;i=i+1) //建议i和j可以是5位以上的带符号数
  for (j=-8;j<=7;j=j+1)
    begin
      if(i>=0)
      in_x={1'b0, i[2:0]};
      else
	  in_x = {1'b1, i[2:0]};
      if(j>=0)
      in_y={1'b0, j[2:0]};  //设置两个输入
      else
	      in_y = {1'b1, j[2:0]};
      sel=3'b000; //ALU的操作码
      k = i+j;    //此处自行计算正确的输出，填入*处
      of= (i+j)>7|(i+j)<-8;    //可分不同情况手工填写
      z = ((i+j)%16)==0;
      c = ((i*j)<0&&((i+j)>=0))||((i<0)&&(j<0));
      begin
	      $display("Info: begin test, A: %d, B: %d", i, j);
      end
      #5 check(k[3:0],of,c,z);
    end
*/
// 测试减法
for(i=-8;i<=7;i=i+1) //建议i和j可以是5位以上的带符号数
  for (j=-8;j<=7;j=j+1)
    begin
      if(i>=0)
      in_x={1'b0, i[2:0]};
      else
	  in_x = {1'b1, i[2:0]};
      if(j>=0)
      in_y={1'b0, j[2:0]};  //设置两个输入
      else
	      in_y = {1'b1, j[2:0]};
      sel=3'b001; //ALU的操作码
      k = i-j;    //此处自行计算正确的输出，填入*处
      of= (i-j)>7|(i-j)<-8;    //可分不同情况手工填写
      z = ((i-j)%16)==0;
      c = ((i*j)>0&&((i-j)>=0))||((i<0)&&(j>0))||(j==0);
      begin
	      $display("Info: begin test, A: %d, B: %d", i, j);
      end
      #5 check(k[3:0],of,c,z);
    end

end

endmodule
